diff options
Diffstat (limited to 'src/xterm.c')
| -rw-r--r-- | src/xterm.c | 156 |
1 files changed, 96 insertions, 60 deletions
diff --git a/src/xterm.c b/src/xterm.c index 2ebe8a80378..c1d1aada530 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -8285,19 +8285,89 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) | |||
| 8285 | "_NET_WM_STATE_STICKY", NULL); | 8285 | "_NET_WM_STATE_STICKY", NULL); |
| 8286 | } | 8286 | } |
| 8287 | 8287 | ||
| 8288 | /* Return the current _NET_WM_STATE. | ||
| 8289 | SIZE_STATE is set to one of the FULLSCREEN_* values. | ||
| 8290 | STICKY is set to 1 if the sticky state is set, 0 if not. */ | ||
| 8291 | |||
| 8292 | static void | ||
| 8293 | get_current_vm_state (struct frame *f, | ||
| 8294 | Window window, | ||
| 8295 | int *size_state, | ||
| 8296 | int *sticky) | ||
| 8297 | { | ||
| 8298 | Atom actual_type; | ||
| 8299 | unsigned long actual_size, bytes_remaining; | ||
| 8300 | int i, rc, actual_format; | ||
| 8301 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | ||
| 8302 | long max_len = 65536; | ||
| 8303 | Display *dpy = FRAME_X_DISPLAY (f); | ||
| 8304 | unsigned char *tmp_data = NULL; | ||
| 8305 | Atom target_type = XA_ATOM; | ||
| 8306 | |||
| 8307 | *sticky = 0; | ||
| 8308 | *size_state = FULLSCREEN_NONE; | ||
| 8309 | |||
| 8310 | BLOCK_INPUT; | ||
| 8311 | x_catch_errors (dpy); | ||
| 8312 | rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state, | ||
| 8313 | 0, max_len, False, target_type, | ||
| 8314 | &actual_type, &actual_format, &actual_size, | ||
| 8315 | &bytes_remaining, &tmp_data); | ||
| 8316 | |||
| 8317 | if (rc != Success || actual_type != target_type || x_had_errors_p (dpy)) | ||
| 8318 | { | ||
| 8319 | if (tmp_data) XFree (tmp_data); | ||
| 8320 | x_uncatch_errors (); | ||
| 8321 | UNBLOCK_INPUT; | ||
| 8322 | return; | ||
| 8323 | } | ||
| 8324 | |||
| 8325 | x_uncatch_errors (); | ||
| 8326 | |||
| 8327 | for (i = 0; i < actual_size; ++i) | ||
| 8328 | { | ||
| 8329 | Atom a = ((Atom*)tmp_data)[i]; | ||
| 8330 | if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) | ||
| 8331 | { | ||
| 8332 | if (*size_state == FULLSCREEN_HEIGHT) | ||
| 8333 | *size_state = FULLSCREEN_MAXIMIZED; | ||
| 8334 | else | ||
| 8335 | *size_state = FULLSCREEN_WIDTH; | ||
| 8336 | } | ||
| 8337 | else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert) | ||
| 8338 | { | ||
| 8339 | if (*size_state == FULLSCREEN_WIDTH) | ||
| 8340 | *size_state = FULLSCREEN_MAXIMIZED; | ||
| 8341 | else | ||
| 8342 | *size_state = FULLSCREEN_HEIGHT; | ||
| 8343 | } | ||
| 8344 | else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom) | ||
| 8345 | *size_state = FULLSCREEN_BOTH; | ||
| 8346 | else if (a == dpyinfo->Xatom_net_wm_state_sticky) | ||
| 8347 | *sticky = 1; | ||
| 8348 | } | ||
| 8349 | |||
| 8350 | if (tmp_data) XFree (tmp_data); | ||
| 8351 | UNBLOCK_INPUT; | ||
| 8352 | } | ||
| 8353 | |||
| 8288 | /* Do fullscreen as specified in extended window manager hints */ | 8354 | /* Do fullscreen as specified in extended window manager hints */ |
| 8289 | 8355 | ||
| 8290 | static int | 8356 | static int |
| 8291 | do_ewmh_fullscreen (struct frame *f) | 8357 | do_ewmh_fullscreen (struct frame *f) |
| 8292 | { | 8358 | { |
| 8293 | int have_net_atom = wm_supports (f, "_NET_WM_STATE"); | 8359 | int have_net_atom = wm_supports (f, "_NET_WM_STATE"); |
| 8360 | Lisp_Object lval = get_frame_param (f, Qfullscreen); | ||
| 8361 | int cur, dummy; | ||
| 8362 | |||
| 8363 | get_current_vm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy); | ||
| 8294 | 8364 | ||
| 8295 | /* Some window managers don't say they support _NET_WM_STATE, but they do say | 8365 | /* Some window managers don't say they support _NET_WM_STATE, but they do say |
| 8296 | they support _NET_WM_STATE_FULLSCREEN. Try that also. */ | 8366 | they support _NET_WM_STATE_FULLSCREEN. Try that also. */ |
| 8297 | if (!have_net_atom) | 8367 | if (!have_net_atom) |
| 8298 | have_net_atom = wm_supports (f, "_NET_WM_STATE_FULLSCREEN"); | 8368 | have_net_atom = wm_supports (f, "_NET_WM_STATE_FULLSCREEN"); |
| 8299 | 8369 | ||
| 8300 | if (have_net_atom) | 8370 | if (have_net_atom && cur != f->want_fullscreen) |
| 8301 | { | 8371 | { |
| 8302 | Lisp_Object frame; | 8372 | Lisp_Object frame; |
| 8303 | const char *fs = "_NET_WM_STATE_FULLSCREEN"; | 8373 | const char *fs = "_NET_WM_STATE_FULLSCREEN"; |
| @@ -8306,26 +8376,41 @@ do_ewmh_fullscreen (struct frame *f) | |||
| 8306 | 8376 | ||
| 8307 | XSETFRAME (frame, f); | 8377 | XSETFRAME (frame, f); |
| 8308 | 8378 | ||
| 8309 | set_wm_state (frame, 0, fs, NULL); | 8379 | /* Keep number of calls to set_wm_state as low as possible. |
| 8310 | set_wm_state (frame, 0, fh, NULL); | 8380 | Some window managers, or possible Gtk+, hangs when too many |
| 8311 | set_wm_state (frame, 0, fw, NULL); | 8381 | are sent at once. */ |
| 8312 | |||
| 8313 | /* If there are _NET_ atoms we assume we have extended window manager | ||
| 8314 | hints. */ | ||
| 8315 | switch (f->want_fullscreen) | 8382 | switch (f->want_fullscreen) |
| 8316 | { | 8383 | { |
| 8317 | case FULLSCREEN_BOTH: | 8384 | case FULLSCREEN_BOTH: |
| 8385 | if (cur == FULLSCREEN_WIDTH || cur == FULLSCREEN_MAXIMIZED | ||
| 8386 | || cur == FULLSCREEN_HEIGHT) | ||
| 8387 | set_wm_state (frame, 0, fw, fh); | ||
| 8318 | set_wm_state (frame, 1, fs, NULL); | 8388 | set_wm_state (frame, 1, fs, NULL); |
| 8319 | break; | 8389 | break; |
| 8320 | case FULLSCREEN_WIDTH: | 8390 | case FULLSCREEN_WIDTH: |
| 8321 | set_wm_state (frame, 1, fw, NULL); | 8391 | if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT |
| 8392 | || cur == FULLSCREEN_MAXIMIZED) | ||
| 8393 | set_wm_state (frame, 0, fs, fh); | ||
| 8394 | if (cur != FULLSCREEN_MAXIMIZED) | ||
| 8395 | set_wm_state (frame, 1, fw, NULL); | ||
| 8322 | break; | 8396 | break; |
| 8323 | case FULLSCREEN_HEIGHT: | 8397 | case FULLSCREEN_HEIGHT: |
| 8324 | set_wm_state (frame, 1, fh, NULL); | 8398 | if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH |
| 8399 | || cur == FULLSCREEN_MAXIMIZED) | ||
| 8400 | set_wm_state (frame, 0, fs, fw); | ||
| 8401 | if (cur != FULLSCREEN_MAXIMIZED) | ||
| 8402 | set_wm_state (frame, 1, fh, NULL); | ||
| 8325 | break; | 8403 | break; |
| 8326 | case FULLSCREEN_MAXIMIZED: | 8404 | case FULLSCREEN_MAXIMIZED: |
| 8405 | if (cur == FULLSCREEN_BOTH) | ||
| 8406 | set_wm_state (frame, 0, fs, NULL); | ||
| 8327 | set_wm_state (frame, 1, fw, fh); | 8407 | set_wm_state (frame, 1, fw, fh); |
| 8328 | break; | 8408 | break; |
| 8409 | case FULLSCREEN_NONE: | ||
| 8410 | if (cur == FULLSCREEN_BOTH) | ||
| 8411 | set_wm_state (frame, 0, fs, NULL); | ||
| 8412 | else | ||
| 8413 | set_wm_state (frame, 0, fw, fh); | ||
| 8329 | } | 8414 | } |
| 8330 | 8415 | ||
| 8331 | f->want_fullscreen = FULLSCREEN_NONE; | 8416 | f->want_fullscreen = FULLSCREEN_NONE; |
| @@ -8351,57 +8436,11 @@ XTfullscreen_hook (FRAME_PTR f) | |||
| 8351 | static void | 8436 | static void |
| 8352 | x_handle_net_wm_state (struct frame *f, XPropertyEvent *event) | 8437 | x_handle_net_wm_state (struct frame *f, XPropertyEvent *event) |
| 8353 | { | 8438 | { |
| 8354 | Atom actual_type; | 8439 | int value = FULLSCREEN_NONE; |
| 8355 | unsigned long actual_size, bytes_remaining; | ||
| 8356 | int i, rc, actual_format, value = FULLSCREEN_NONE; | ||
| 8357 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | ||
| 8358 | long max_len = 65536; | ||
| 8359 | Display *dpy = FRAME_X_DISPLAY (f); | ||
| 8360 | unsigned char *tmp_data = NULL; | ||
| 8361 | Atom target_type = XA_ATOM; | ||
| 8362 | Lisp_Object lval; | 8440 | Lisp_Object lval; |
| 8363 | int sticky = 0; | 8441 | int sticky = 0; |
| 8364 | 8442 | ||
| 8365 | BLOCK_INPUT; | 8443 | get_current_vm_state (f, event->window, &value, &sticky); |
| 8366 | x_catch_errors (dpy); | ||
| 8367 | rc = XGetWindowProperty (dpy, event->window, | ||
| 8368 | event->atom, 0, max_len, False, target_type, | ||
| 8369 | &actual_type, &actual_format, &actual_size, | ||
| 8370 | &bytes_remaining, &tmp_data); | ||
| 8371 | |||
| 8372 | if (rc != Success || actual_type != target_type || x_had_errors_p (dpy)) | ||
| 8373 | { | ||
| 8374 | if (tmp_data) XFree (tmp_data); | ||
| 8375 | x_uncatch_errors (); | ||
| 8376 | UNBLOCK_INPUT; | ||
| 8377 | return; | ||
| 8378 | } | ||
| 8379 | |||
| 8380 | x_uncatch_errors (); | ||
| 8381 | |||
| 8382 | for (i = 0; i < actual_size; ++i) | ||
| 8383 | { | ||
| 8384 | Atom a = ((Atom*)tmp_data)[i]; | ||
| 8385 | if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) | ||
| 8386 | { | ||
| 8387 | if (value == FULLSCREEN_HEIGHT) | ||
| 8388 | value = FULLSCREEN_MAXIMIZED; | ||
| 8389 | else | ||
| 8390 | value = FULLSCREEN_WIDTH; | ||
| 8391 | } | ||
| 8392 | else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert) | ||
| 8393 | { | ||
| 8394 | if (value == FULLSCREEN_WIDTH) | ||
| 8395 | value = FULLSCREEN_MAXIMIZED; | ||
| 8396 | else | ||
| 8397 | value = FULLSCREEN_HEIGHT; | ||
| 8398 | } | ||
| 8399 | else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom) | ||
| 8400 | value = FULLSCREEN_BOTH; | ||
| 8401 | else if (a == dpyinfo->Xatom_net_wm_state_sticky) | ||
| 8402 | sticky = 1; | ||
| 8403 | } | ||
| 8404 | |||
| 8405 | lval = Qnil; | 8444 | lval = Qnil; |
| 8406 | switch (value) | 8445 | switch (value) |
| 8407 | { | 8446 | { |
| @@ -8421,9 +8460,6 @@ x_handle_net_wm_state (struct frame *f, XPropertyEvent *event) | |||
| 8421 | 8460 | ||
| 8422 | store_frame_param (f, Qfullscreen, lval); | 8461 | store_frame_param (f, Qfullscreen, lval); |
| 8423 | store_frame_param (f, Qsticky, sticky ? Qt : Qnil); | 8462 | store_frame_param (f, Qsticky, sticky ? Qt : Qnil); |
| 8424 | |||
| 8425 | if (tmp_data) XFree (tmp_data); | ||
| 8426 | UNBLOCK_INPUT; | ||
| 8427 | } | 8463 | } |
| 8428 | 8464 | ||
| 8429 | /* Check if we need to resize the frame due to a fullscreen request. | 8465 | /* Check if we need to resize the frame due to a fullscreen request. |