From 716971655eb9ab7909447e2f5d4911b6f45164bb Mon Sep 17 00:00:00 2001 From: hurikhan Date: Sat, 17 Jan 2015 00:18:45 +0900 Subject: [PATCH] added the following methods: * set_minimized(bool) * bool is_minimized() * set_maximized(bool) * bool is_maximized() --- core/bind/core_bind.cpp | 22 ++- core/bind/core_bind.h | 12 +- core/os/os.h | 4 + demos/misc/window_management/control.gd | 33 ++++- .../window_management/window_management.scn | Bin 3931 -> 4111 bytes platform/x11/os_x11.cpp | 137 +++++++++++++++++- platform/x11/os_x11.h | 4 + 7 files changed, 194 insertions(+), 18 deletions(-) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 1fb6f96e71c..6919c70a5fa 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -228,6 +228,22 @@ void _OS::set_resizable(bool p_enabled) { bool _OS::is_resizable() const { return OS::get_singleton()->is_resizable(); } + +void _OS::set_minimized(bool p_enabled) { + OS::get_singleton()->set_minimized(p_enabled); +} + +bool _OS::is_minimized() const { + return OS::get_singleton()->is_minimized(); +} + +void _OS::set_maximized(bool p_enabled) { + OS::get_singleton()->set_maximized(p_enabled); +} + +bool _OS::is_maximized() const { + return OS::get_singleton()->is_maximized(); +} #endif void _OS::set_use_file_access_save_and_swap(bool p_enable) { @@ -698,7 +714,11 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_fullscreen","enabled"),&_OS::set_fullscreen); ObjectTypeDB::bind_method(_MD("is_fullscreen"),&_OS::is_fullscreen); ObjectTypeDB::bind_method(_MD("set_resizable","enabled"),&_OS::set_resizable); - ObjectTypeDB::bind_method(_MD("is_resizable"),&_OS::is_resizable); + ObjectTypeDB::bind_method(_MD("is_resizable"),&_OS::is_resizable); + ObjectTypeDB::bind_method(_MD("set_minimized", "enabled"),&_OS::set_minimized); + ObjectTypeDB::bind_method(_MD("is_minimized"),&_OS::is_minimized); + ObjectTypeDB::bind_method(_MD("set_maximized", "enabled"),&_OS::set_maximized); + ObjectTypeDB::bind_method(_MD("is_maximized"),&_OS::is_maximized); #endif ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 7ffd7e9e7ca..b6f4f8eef46 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -118,10 +118,14 @@ public: virtual void set_window_position(const Point2& p_position); virtual Size2 get_window_size() const; virtual void set_window_size(const Size2& p_size); - void set_fullscreen(bool p_enabled); - bool is_fullscreen() const; - void set_resizable(bool p_enabled); - bool is_resizable() const; + virtual void set_fullscreen(bool p_enabled); + virtual bool is_fullscreen() const; + virtual void set_resizable(bool p_enabled); + virtual bool is_resizable() const; + virtual void set_minimized(bool p_enabled); + virtual bool is_minimized() const; + virtual void set_maximized(bool p_enabled); + virtual bool is_maximized() const; #endif Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); diff --git a/core/os/os.h b/core/os/os.h index f1a9de1edf2..c04a91e3029 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -164,6 +164,10 @@ public: virtual bool is_fullscreen() const=0; virtual void set_resizable(bool p_enabled)=0; virtual bool is_resizable() const=0; + virtual void set_minimized(bool p_enabled)=0; + virtual bool is_minimized() const=0; + virtual void set_maximized(bool p_enabled)=0; + virtual bool is_maximized() const=0; #endif virtual void set_iterations_per_second(int p_ips); diff --git a/demos/misc/window_management/control.gd b/demos/misc/window_management/control.gd index 043db8d4890..fd746cf036f 100644 --- a/demos/misc/window_management/control.gd +++ b/demos/misc/window_management/control.gd @@ -13,17 +13,25 @@ func _fixed_process(delta): if(!OS.is_resizable()): modetext += "FixedSize\n" + if(OS.is_minimized()): + modetext += "Minimized\n" + + if(OS.is_maximized()): + modetext += "Maximized\n" + get_node("Label_Mode").set_text(modetext) get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) ) get_node("Label_Size").set_text(str("Size:\n", OS.get_window_size() ) ) - get_node("Label_Screen_Info").set_text( str("Screens:\n", OS.get_screen_count(),"\n\nCurrent:\n", OS.get_screen() ) ) + get_node("Label_Screen_Count").set_text( str("Screens:\n", OS.get_screen_count() ) ) + + get_node("Label_Screen_Current").set_text( str("Current:\n", OS.get_screen() ) ) get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) ) - get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position())) + get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) ) if(OS.get_screen_count() > 1): @@ -50,8 +58,9 @@ func _fixed_process(delta): OS.set_fullscreen(false) get_node("Button_FixedSize").set_pressed( !OS.is_resizable() ) - - + get_node("Button_Minimized").set_pressed( OS.is_minimized() ) + get_node("Button_Maximized").set_pressed( OS.is_maximized() ) + func _ready(): set_fixed_process(true) @@ -79,9 +88,6 @@ func _on_Button_Screen1_pressed(): OS.set_screen(1) - - - func _on_Button_FixedSize_pressed(): if(OS.is_resizable()): OS.set_resizable(false) @@ -89,3 +95,16 @@ func _on_Button_FixedSize_pressed(): OS.set_resizable(true) + +func _on_Button_Minimized_pressed(): + if(OS.is_minimized()): + OS.set_minimized(false) + else: + OS.set_minimized(true) + + +func _on_Button_Maximized_pressed(): + if(OS.is_maximized()): + OS.set_maximized(false) + else: + OS.set_maximized(true) diff --git a/demos/misc/window_management/window_management.scn b/demos/misc/window_management/window_management.scn index a83897f9a08af20a0ee92b9f52f8c358fa1b1ab7..635f6f6f28ba59ae2a8af372b4d8e9d43f5e397d 100644 GIT binary patch delta 2301 zcmY*bYj6|S6+XKwd2P#Bz}lAIzOrl!*`YR1w>Uv(^{{MQLTZN?aFbn07M6l78A-MY zFp+H164MgGXaWiJp+K6FG6`X5hhaJm!u~-fBw^CWxGkOWl}$^DnbL*~bofK>x@o7~ zneXn|^SJw+v-h0Y8`Vchd3TS~3EH(3pwcCJ z4G{_Ysji6g?nxKnne@hnYh(^ueATDW9HDt;Sf!eE-}L$dgXEayUi;6~LT^rbgD>RV z61d1U57mE~x~3zE@u!kTA+TpyaeY^Por^}Sr|Mr->mcU+5y_X^T=zxqNIWtY^$x2q za3jN(j~Y@hy@-bTDp35-G~~;oI;~Tlio`;-%OR{DO)mHLIDVKe^se9(C)sykhU!ax za-#hUDwINte4dXCj;MW3J=IrI7^Pw>Bvw(W6;@HM6}ufnbKJY2OdN&&eqYAW;m3wI zzntiuIF+{f-XjK@W1EOjutAmOD&;+Mu#Xy9!UyS6GL@o0ItD548y|%hT3pR`gz8S0 zyRQx)CVvV7dA~D=CeL2WI3HI0-f5;O$Hq)~0>ZVwqkOq*7nVD^xl!+mfAHaWEZ7Dv z(u$QCaJ{1gNZNtwfEF7&AK)>02oGY=!Gq$vY2C#S502Dd0;S;3WX^0GG;Z>))q&D?9FTk(~!);;Y}cPTy!;H;pYQs5@}KYc(!K z1FT8D?0z1XJJ0j|ft{8+w%vR*61V*oyZQZpAnF*_!rsn}SR?>Ebh3aJL#H1__O#Z4 z68ePEP++X9YrF)jg7K=4^90Nt1Jh=+qCUn$#E%D z)j276hkPN=z=5}SeW{v+6K|Al%rGi%H99AAW5LLnG7t^*>w#zez!3rT3M9_IROIXp2fR_xkv!p(k3W6_SHTiuFt7r6M+W1n5{nM_)YYt_m0%>fq%wan zG!Tp{tT4(RwN2R2zT1w~P)e#x6(!IgibtYKbR?|A0`Yh#JP=b9C?^%b69KLGTE2fI z7LN=m-snI~l^~x~q}JzJwourq9R>3H93|$D1_EI+fCNNB^gaG)XgIF6$_03Warm6! z5IYdPunY@?{~WDlM&VfKO-y!i!wwYXjj0Q{+x1z#5dV@Y%d0Ke1O}E{`^eznxRUbZ ztxVk2w}1`jEeeKiqEGe3ZWWH$%(YB#p=o4tFe&I}!CGyFXH0iV&k@TB7t zohK5HklMo98fZyRz=!F_;Gy~?&8dS`={nGAs; zOzm<$jfu}P#az8hZROCQzT)_GauQ-00)HPL<&qNX#T@5IG#UuUneK1NvmEBDge!)O z%(W2n*2O7s07&vBF0)Ln<0XLfPG+I-cDj~>L+Vc{=V2YJ_uyU1*_kBRSu@N+*j&iR zfRHXIyHEZEkJ3O2Rlq`0;(GzXG3ofu)N85T`BjN1RzNPP!&bQ$jq-669lyXPSCADp zi))~eG^6OciX!ep(OH5bEGISCLj_=;NWhb5r{YQHJD9-V;68afI-!KP@CcZQh)0}< z@rdhJIPG4FF{og1KZZ)CzXnxoy#Uo|kqW6LhR?VcQ?rJt1pV5)`y>_S-4gAacgLu8 z9(pw0jHa7qx^}y!dpbSuHvQSu3tLH(>zrF@Kdk{5TnE_wEbUsjDem(asC5CJA(!0> z6FdgE|7`H>MVeh!N{BjWXNUkGUyn5EHLq3 zzEGsS7;6}jZA1qx-#ZNZOaniju>`3c_XrTh|lOk+90mnsZ8X4wC7w>LeRcxFX3W z&9qN5g|h1304yOoM3HllO;z&Vn%R~<686}Y5TwEE7IJU)pI>-kw9-2Ju^A}NI0zZ z*Ai%9sTQ|yg)lL|5D`3w84(+rV3-s@ga{dv=XS;fyD4w#SjL1X6CjTmm>6TL$2G~M gI8$2L+|sloY;A^uMR}BsW^JTvS9edhQ~T%n7p%CY(f|Me delta 2056 zcmXw44NM#78Gi51a9|T0asd;5KQIQ&k061T43hBPoiTPumkC1BgoHcW7~=vyVw;jO zR6C?i(`XgxTs3XcG*eAY)lU1-Hmy^n#ehP$Dbb{DS-N#o&alBMvT71tCuN$t&slfU zbN75d&!_i&zxUBCkdG@$`UhkgGS6;+K^wpp5Aa?V1@mgjyG;0ptH0yg)#sCYYnR9e z(CYc@?V_q4J+}(>t5t?$9aNOZN(@||E?3q%ZW2UF9$=cuxC(u;01B$Q7ri+)= zRfF<1EfTEy8-&zX<9j@IaWk3ksW&L@(5U8Z)VV@v6(?D3Vp9tLCHp!P1ZDmy7#XQZnOv1vyY$C-VSYGi_dY{RdbWMOQ3pGeTQBKs?>cno zKzcWImRu}>R=u!-9s?DwpF8eZXCWenfg>T;I$E5cRsWj}DZZ)=h^i&hSgHg<)z9f{ ziK75Z#Lt;$W1jkPHWZBnegfU3-@&H9VPyg0SfsO{7nAlFank!2eb7*7;EDW8w1_ATWq&A=()|VAft_5 z{yV>5DqUrc_*bzNIrR+A$-l?lXo9x*6~|w2k37hZ_(!eR>bKdj7PWh^pPl;yQD?9k zW?diPUJl@qoDsPGj65B*ODLe#%RL+P&m6sdu?WjWzjzL-aK+|(=`@yc55M5YM>;WyuXMfzE)+|6;GNpG;%bm^V(kZR%HdUM~A6ph7JjpOpmS&=bqMhP^p z=?1sFqwce-wmjWXD!%};58*xT?wvb_vG3@$)SFx+9Pp|KXvNCpeo_`sI6C2i&&hT= z&#NyPi{TJ}qWDLGQLQkngr`GF#2<|YLxG5*KnXPxOE}1)$RnK5Hyw#;lZq!Ch^PV> ziIAAfv7XuWr9Q0C+YSUt(BKRE{UH)Sf=!t#%m#)uLNVbGz<>qNgX|a;x*4U?RDkb9!Rp;!t8X zw>h?*>Ajg ztbsfVgBp>Z%03kgjc7Ce)IVWeEyi!;WULwuYN5_#C+t&CK{lDgrBoqfbEuD))b2RX z0wTW63NZlDL%wBJjIs+!c9HZ)kq=CEhNQ;}ib*+?r8ent_P7~hQ2xpRf42F_CoF#lO59bIk{tJea ze9uB}ThB~y2PiZZo>3uQ2Ohf3OI07!2D^_S3g9C-@CAW%hv2#{?JNtux6%>8)sf}| z+(}mo%m}0p3sMUmyH@FnyDQxyfInR=+!i*tF3BQyt?}-W@5^28#k4FK+G#(Xp)Le7 z^~4ZGJH=UwY>IOfJjF0gl!v2)hbQRhs}wmD3Wb4inLsQ5A1LglTLCK(;AA46UmSys z-`eQpC5+KC28bEEP@}Aan4yNQ9i%W)e1+mkicY$>6uJmck2r+XTyQvZBpi9nyD1Ma z2yq@n8cq=v$aG4Br>S5kQ(!b_3M>j}P74CY5}EV^B=BX;L^E>Bf@qz4*Mz&82 zg=kZgU5-L5bl6~=ruPitB>5A%-HsNRBzZ7FxRk|lH)Vm4&RQJzDA6c^Tw{2TyOvY diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index c6fdc24768d..ef92d190c9b 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -37,7 +37,16 @@ #include "X11/Xutil.h" #ifdef EXPERIMENTAL_WM_API +#include "X11/Xatom.h" #include "X11/extensions/Xinerama.h" +// ICCCM +#define WM_NormalState 1L // window normal state +#define WM_IconicState 3L // window minimized + +// EWMH +#define _NET_WM_STATE_REMOVE 0L // remove/unset property +#define _NET_WM_STATE_ADD 1L // add/set property +#define _NET_WM_STATE_TOGGLE 2L // toggle property #endif #include "main/main.h" @@ -214,6 +223,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); #else + minimized = false; + minimized = false; window_data.position.x = 0; window_data.position.y = 0; window_data.size.width = 800; @@ -549,7 +560,7 @@ void OS_X11::set_wm_border(bool p_enabled) { } void OS_X11::set_wm_fullscreen(bool p_enabled) { - // code for netwm-compliants + // Using EWMH -- Extened Window Manager Hints XEvent xev; Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); @@ -559,7 +570,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { xev.xclient.window = x11_window; xev.xclient.message_type = wm_state; xev.xclient.format = 32; - xev.xclient.data.l[0] = p_enabled ? 1L : 0L; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xev.xclient.data.l[1] = wm_fullscreen; xev.xclient.data.l[2] = 0; @@ -567,6 +578,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { } int OS_X11::get_screen_count() const { + // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); if( !ext_okay ) return 0; @@ -611,6 +623,7 @@ void OS_X11::set_screen(int p_screen) { } Point2 OS_X11::get_screen_position(int p_screen) const { + // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); if( !ext_okay ) return Point2i(0,0); @@ -625,6 +638,7 @@ Point2 OS_X11::get_screen_position(int p_screen) const { } Size2 OS_X11::get_screen_size(int p_screen) const { + // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); if( !ext_okay ) return Size2i(0,0); @@ -651,14 +665,14 @@ void OS_X11::set_window_position(const Point2& p_position) { if( current_videomode.fullscreen ) return; - // _NET_FRAME_EXTENTS + // Using EWMH -- Extended Window Manager Hints + // to get the size of the decoration Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); Atom type; int format; unsigned long len; unsigned long remaining; unsigned char *data = NULL; - //long *extends; int result; result = XGetWindowProperty( @@ -759,7 +773,6 @@ void OS_X11::set_resizable(bool p_enabled) { xsh->max_width = xwa.width; xsh->min_height = xwa.height; xsh->max_height = xwa.height; - printf("%d %d\n", xwa.width, xwa.height); } XSetWMNormalHints(x11_display, x11_window, xsh); XFree(xsh); @@ -770,6 +783,119 @@ void OS_X11::set_resizable(bool p_enabled) { bool OS_X11::is_resizable() const { return current_videomode.resizable; } + +void OS_X11::set_minimized(bool p_enabled) { + // Using ICCCM -- Inter-Client Communication Conventions Manual + XEvent xev; + Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_change; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); +} + +bool OS_X11::is_minimized() const { + // Using ICCCM -- Inter-Client Communication Conventions Manual + Atom property = XInternAtom(x11_display,"WM_STATE", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data + ); + + if( result == Success ) { + long *state = (long *) data; + if( state[0] == 3L ) + return true; + } + return false; +} + +void OS_X11::set_maximized(bool p_enabled) { + // Using EWMH -- Extended Window Manager Hints + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_max_horz; + xev.xclient.data.l[2] = wm_max_vert; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); + + maximized = p_enabled; +} + +bool OS_X11::is_maximized() const { + // Using EWMH -- Extended Window Manager Hints + Atom property = XInternAtom(x11_display,"_NET_WM_STATE",False ); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 1024, + False, + XA_ATOM, + &type, + &format, + &len, + &remaining, + &data + ); + + if(result == Success) { + Atom *atoms = (Atom*) data; + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + bool found_wm_max_horz = false; + bool found_wm_max_vert = false; + + for( unsigned int i=0; i < len; i++ ) { + if( atoms[i] == wm_max_horz ) + found_wm_max_horz = true; + if( atoms[i] == wm_max_vert ) + found_wm_max_vert = true; + + if( found_wm_max_horz && found_wm_max_vert ) + return true; + } + } + + return false; +} #endif InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) { @@ -1719,4 +1845,3 @@ OS_X11::OS_X11() { xim_style=0L; mouse_mode=MOUSE_MODE_VISIBLE; }; - diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index d286efe7b84..557052ab693 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -241,6 +241,10 @@ public: virtual bool is_fullscreen() const; virtual void set_resizable(bool p_enabled); virtual bool is_resizable() const; + virtual void set_minimized(bool p_enabled); + virtual bool is_minimized() const; + virtual void set_maximized(bool p_enabled); + virtual bool is_maximized() const; #endif virtual void move_window_to_foreground();