int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); wm_window_close(C, wm, win); return OPERATOR_FINISHED; }
/* operator entry */ int wm_homefile_write_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); char filepath[FILE_MAX]; int fileflags; /* check current window and close it if temp */ if (win && win->screen->temp) wm_window_close(C, wm, win); /* update keymaps in user preferences */ WM_keyconfig_update(wm); BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); printf("trying to save homefile at %s ", filepath); /* force save as regular blend file */ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY); if (BLO_write_file(CTX_data_main(C), filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) { printf("fail\n"); return OPERATOR_CANCELLED; } printf("ok\n"); G.save_over = 0; return OPERATOR_FINISHED; }
/** * Call after #wm_window_ghostwindows_ensure or #WM_check * (after loading a new file) in the unlikely event a window couldn't be created. */ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm) { wmWindow *win, *win_next; BLI_assert(G.background == false); for (win = wm->windows.first; win; win = win_next) { win_next = win->next; if (win->ghostwin == NULL) { wm_window_close(C, wm, win); } } }
int wm_stereo3d_set_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); const bool is_fullscreen = WM_window_is_fullscreen(win); char display_mode = win->stereo3d_format->display_mode; if (G.background) return OPERATOR_CANCELLED; if (op->customdata) { Stereo3dData *s3dd = op->customdata; *win->stereo3d_format = s3dd->stereo3d_format; } /* pageflip requires a new window to be created with the proper OS flags */ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { if (wm_stereo3d_quadbuffer_supported() == false) { BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); win->stereo3d_format->display_mode = display_mode; return OPERATOR_CANCELLED; } if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { wm_window_close(C, wm, win); win = wm->windows.last; } else { BKE_report(op->reports, RPT_ERROR, "Fail to create a window compatible with time sequential (page-flip) display method"); win->stereo3d_format->display_mode = display_mode; return OPERATOR_CANCELLED; } } if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { if (!is_fullscreen) { BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } } if (op->customdata) { MEM_freeN(op->customdata); } WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; }
/** * A higher level version of copy that tests the new window can be added. * (called from the operator directly) */ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_dst; win_dst = wm_window_copy(C, win_src); WM_check(C); if (win_dst->ghostwin) { WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL); return win_dst; } else { wm_window_close(C, wm, win_dst); return NULL; } }
/* operator entry */ int WM_write_homefile(bContext *C, wmOperator *op) { wmWindowManager *wm= CTX_wm_manager(C); wmWindow *win= CTX_wm_window(C); char tstr[FILE_MAXDIR+FILE_MAXFILE]; int fileflags; /* check current window and close it if temp */ if(win->screen->full == SCREENTEMP) wm_window_close(C, wm, win); BLI_make_file_string("/", tstr, BLI_gethome(), ".B25.blend"); /* force save as regular blend file */ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN); BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports); G.save_over= 0; return OPERATOR_FINISHED; }
/** * new window, no screen yet, but we open ghostwindow for it, * also gets the window level handlers * \note area-rip calls this. * \return the window or NULL. */ wmWindow *WM_window_open(bContext *C, const rcti *rect) { wmWindow *win_prev = CTX_wm_window(C); wmWindow *win = wm_window_new(C); win->posx = rect->xmin; win->posy = rect->ymin; win->sizex = BLI_rcti_size_x(rect); win->sizey = BLI_rcti_size_y(rect); win->drawmethod = U.wmdrawmethod; WM_check(C); if (win->ghostwin) { return win; } else { wm_window_close(C, CTX_wm_manager(C), win); CTX_wm_window_set(C, win_prev); return NULL; } }
int wm_stereo3d_set_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_src = CTX_wm_window(C); wmWindow *win_dst = NULL; const bool is_fullscreen = WM_window_is_fullscreen(win_src); char prev_display_mode = win_src->stereo3d_format->display_mode; Stereo3dData *s3dd; bool ok = true; if (G.background) return OPERATOR_CANCELLED; if (op->customdata == NULL) { /* no invoke means we need to set the operator properties here */ wm_stereo3d_set_init(C, op); wm_stereo3d_set_properties(C, op); } s3dd = op->customdata; *win_src->stereo3d_format = s3dd->stereo3d_format; if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && prev_display_mode != win_src->stereo3d_format->display_mode) { /* in case the hardward supports pageflip but not the display */ if ((win_dst = wm_window_copy_test(C, win_src))) { /* pass */ } else { BKE_report(op->reports, RPT_ERROR, "Failed to create a window without quad-buffer support, you may experience flickering"); ok = false; } } else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { /* ED_screen_duplicate() can't handle other cases yet T44688 */ if (win_src->screen->state != SCREENNORMAL) { BKE_report(op->reports, RPT_ERROR, "Failed to switch to Time Sequential mode when in fullscreen"); ok = false; } /* pageflip requires a new window to be created with the proper OS flags */ else if ((win_dst = wm_window_copy_test(C, win_src))) { if (wm_stereo3d_quadbuffer_supported()) { BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); } else { wm_window_close(C, wm, win_dst); win_dst = NULL; BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); ok = false; } } else { BKE_report(op->reports, RPT_ERROR, "Failed to create a window compatible with the time sequential display method"); ok = false; } } if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) { if (!is_fullscreen) { BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } } MEM_freeN(op->customdata); if (ok) { if (win_dst) { wm_window_close(C, wm, win_src); } WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; } else { /* without this, the popup won't be freed freed properly T44688 */ CTX_wm_window_set(C, win_src); win_src->stereo3d_format->display_mode = prev_display_mode; return OPERATOR_CANCELLED; } }
/* called by ghost, here we handle events for windows themselves or send to event system */ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) { bContext *C = C_void_ptr; wmWindowManager *wm = CTX_wm_manager(C); GHOST_TEventType type = GHOST_GetEventType(evt); int time = GHOST_GetEventTime(evt); if (type == GHOST_kEventQuit) { WM_exit(C); } else { GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt); GHOST_TEventDataPtr data = GHOST_GetEventData(evt); wmWindow *win; if (!ghostwin) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has no window"); return 1; } else if (!GHOST_ValidWindow(g_system, ghostwin)) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has invalid window"); return 1; } else { win = GHOST_GetWindowUserData(ghostwin); } switch (type) { case GHOST_kEventWindowDeactivate: wm_event_add_ghostevent(wm, win, type, time, data); win->active = 0; /* XXX */ break; case GHOST_kEventWindowActivate: { GHOST_TEventKeyData kdata; wmEvent event; int cx, cy, wx, wy; wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; // window_handle(win, INPUTCHANGE, win->active); /* bad ghost support for modifier keys... so on activate we set the modifiers again */ kdata.ascii = '\0'; kdata.utf8_buf[0] = '\0'; if (win->eventstate->shift && !query_qual(SHIFT)) { kdata.key = GHOST_kKeyLeftShift; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->ctrl && !query_qual(CONTROL)) { kdata.key = GHOST_kKeyLeftControl; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->alt && !query_qual(ALT)) { kdata.key = GHOST_kKeyLeftAlt; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } if (win->eventstate->oskey && !query_qual(OS)) { kdata.key = GHOST_kKeyOS; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ win->eventstate->keymodifier = 0; /* entering window, update mouse pos. but no event */ GHOST_GetCursorPosition(g_system, &wx, &wy); GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy); win->eventstate->x = cx; win->eventstate->y = (win->sizey - 1) - cy; win->addmousemove = 1; /* enables highlighted buttons */ wm_window_make_drawable(C, win); /* window might be focused by mouse click in configuration of window manager * when focus is not following mouse * click could have been done on a button and depending on window manager settings * click would be passed to blender or not, but in any case button under cursor * should be activated, so at max next click on button without moving mouse * would trigger it's handle function * currently it seems to be common practice to generate new event for, but probably * we'll need utility function for this? (sergey) */ event = *(win->eventstate); event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm_event_add(win, &event); break; } case GHOST_kEventWindowClose: { wm_window_close(C, wm, win); break; } case GHOST_kEventWindowUpdate: { if (G.debug & G_DEBUG_EVENTS) { printf("%s: ghost redraw %d\n", __func__, win->winid); } wm_window_make_drawable(C, win); WM_event_add_notifier(C, NC_WINDOW, NULL); break; } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { GHOST_TWindowState state; state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; int l, t, r, b, scr_w, scr_h; int sizex, sizey, posx, posy; client_rect = GHOST_GetClientBounds(win->ghostwin); GHOST_GetRectangle(client_rect, &l, &t, &r, &b); GHOST_DisposeRectangle(client_rect); wm_get_screensize(&scr_w, &scr_h); sizex = r - l; sizey = b - t; posx = l; posy = scr_h - t - win->sizey; /* * Ghost sometimes send size or move events when the window hasn't changed. * One case of this is using compiz on linux. To alleviate the problem * we ignore all such event here. * * It might be good to eventually do that at Ghost level, but that is for * another time. */ if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || win->posy != posy) { win->sizex = sizex; win->sizey = sizey; win->posx = posx; win->posy = posy; /* debug prints */ if (G.debug & G_DEBUG_EVENTS) { const char *state_str; state = GHOST_GetWindowState(win->ghostwin); if (state == GHOST_kWindowStateNormal) { state_str = "normal"; } else if (state == GHOST_kWindowStateMinimized) { state_str = "minimized"; } else if (state == GHOST_kWindowStateMaximized) { state_str = "maximized"; } else if (state == GHOST_kWindowStateFullScreen) { state_str = "fullscreen"; } else { state_str = "<unknown>"; } printf("%s: window %d state = %s\n", __func__, win->winid, state_str); if (type != GHOST_kEventWindowSize) { printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); } } wm_window_make_drawable(C, win); wm_draw_window_clear(win); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); } } break; } case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; wmWindow *oldWindow; char *path = GHOST_GetEventData(evt); if (path) { /* operator needs a valid window in context, ensures * it is correctly set */ oldWindow = CTX_wm_window(C); CTX_wm_window_set(C, win); WM_operator_properties_create(&props_ptr, "WM_OT_open_mainfile"); RNA_string_set(&props_ptr, "filepath", path); WM_operator_name_call(C, "WM_OT_open_mainfile", WM_OP_EXEC_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); CTX_wm_window_set(C, oldWindow); } break; } case GHOST_kEventDraggingDropDone: { wmEvent event; GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); int cx, cy, wx, wy; /* entering window, update mouse pos */ GHOST_GetCursorPosition(g_system, &wx, &wy); GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy); win->eventstate->x = cx; win->eventstate->y = (win->sizey - 1) - cy; event = *(win->eventstate); /* copy last state, like mouse coords */ /* activate region */ event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; wm_event_add(win, &event); /* make blender drop event with custom data pointing to wm drags */ event.type = EVT_DROP; event.val = KM_RELEASE; event.custom = EVT_DATA_LISTBASE; event.customdata = &wm->drags; event.customdatafree = 1; wm_event_add(win, &event); /* printf("Drop detected\n"); */ /* add drag data to wm for paths: */ if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { GHOST_TStringArray *stra = ddd->data; int a, icon; for (a = 0; a < stra->count; a++) { printf("drop file %s\n", stra->strings[a]); /* try to get icon type from extension */ icon = ED_file_extension_icon((char *)stra->strings[a]); WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0); /* void poin should point to string, it makes a copy */ break; /* only one drop element supported now */ } } break; } default: wm_event_add_ghostevent(wm, win, type, time, data); break; } } return 1; }
/* mouse coordinate converversion happens here */ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) { bContext *C = C_void_ptr; wmWindowManager *wm = CTX_wm_manager(C); GHOST_TEventType type = GHOST_GetEventType(evt); int time = GHOST_GetEventTime(evt); if (type == GHOST_kEventQuit) { WM_exit(C); } else { GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt); GHOST_TEventDataPtr data = GHOST_GetEventData(evt); wmWindow *win; /* Ghost now can call this function for life resizes, but it should return if WM didn't initialize yet. * Can happen on file read (especially full size window) */ if ((wm->initialized & WM_INIT_WINDOW) == 0) { return 1; } if (!ghostwin) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has no window"); return 1; } else if (!GHOST_ValidWindow(g_system, ghostwin)) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has invalid window"); return 1; } else { win = GHOST_GetWindowUserData(ghostwin); } switch (type) { case GHOST_kEventWindowDeactivate: wm_event_add_ghostevent(wm, win, type, time, data); win->active = 0; /* XXX */ /* clear modifiers for inactive windows */ win->eventstate->alt = 0; win->eventstate->ctrl = 0; win->eventstate->shift = 0; win->eventstate->oskey = 0; win->eventstate->keymodifier = 0; break; case GHOST_kEventWindowActivate: { GHOST_TEventKeyData kdata; wmEvent event; int wx, wy; const int keymodifier = ((query_qual(SHIFT) ? KM_SHIFT : 0) | (query_qual(CONTROL) ? KM_CTRL : 0) | (query_qual(ALT) ? KM_ALT : 0) | (query_qual(OS) ? KM_OSKEY : 0)); /* Win23/GHOST modifier bug, see T40317 */ #ifndef WIN32 //# define USE_WIN_ACTIVATE #endif wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; // window_handle(win, INPUTCHANGE, win->active); /* bad ghost support for modifier keys... so on activate we set the modifiers again */ /* TODO: This is not correct since a modifier may be held when a window is activated... * better solve this at ghost level. attempted fix r54450 but it caused bug [#34255] * * For now don't send GHOST_kEventKeyDown events, just set the 'eventstate'. */ kdata.ascii = '\0'; kdata.utf8_buf[0] = '\0'; if (win->eventstate->shift) { if ((keymodifier & KM_SHIFT) == 0) { kdata.key = GHOST_kKeyLeftShift; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_SHIFT) { win->eventstate->shift = KM_MOD_FIRST; } } #endif if (win->eventstate->ctrl) { if ((keymodifier & KM_CTRL) == 0) { kdata.key = GHOST_kKeyLeftControl; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_CTRL) { win->eventstate->ctrl = KM_MOD_FIRST; } } #endif if (win->eventstate->alt) { if ((keymodifier & KM_ALT) == 0) { kdata.key = GHOST_kKeyLeftAlt; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_ALT) { win->eventstate->alt = KM_MOD_FIRST; } } #endif if (win->eventstate->oskey) { if ((keymodifier & KM_OSKEY) == 0) { kdata.key = GHOST_kKeyOS; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_OSKEY) { win->eventstate->oskey = KM_MOD_FIRST; } } #endif #undef USE_WIN_ACTIVATE /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ win->eventstate->keymodifier = 0; /* entering window, update mouse pos. but no event */ wm_get_cursor_position(win, &wx, &wy); win->eventstate->x = wx; win->eventstate->y = wy; win->addmousemove = 1; /* enables highlighted buttons */ wm_window_make_drawable(wm, win); /* window might be focused by mouse click in configuration of window manager * when focus is not following mouse * click could have been done on a button and depending on window manager settings * click would be passed to blender or not, but in any case button under cursor * should be activated, so at max next click on button without moving mouse * would trigger it's handle function * currently it seems to be common practice to generate new event for, but probably * we'll need utility function for this? (sergey) */ wm_event_init_from_window(win, &event); event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm_event_add(win, &event); break; } case GHOST_kEventWindowClose: { wm_window_close(C, wm, win); break; } case GHOST_kEventWindowUpdate: { if (G.debug & G_DEBUG_EVENTS) { printf("%s: ghost redraw %d\n", __func__, win->winid); } wm_window_make_drawable(wm, win); WM_event_add_notifier(C, NC_WINDOW, NULL); break; } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { GHOST_TWindowState state; state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; /* stop screencast if resize */ if (type == GHOST_kEventWindowSize) { WM_jobs_stop(wm, win->screen, NULL); } /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; int l, t, r, b, scr_w, scr_h; int sizex, sizey, posx, posy; client_rect = GHOST_GetClientBounds(win->ghostwin); GHOST_GetRectangle(client_rect, &l, &t, &r, &b); GHOST_DisposeRectangle(client_rect); wm_get_desktopsize(&scr_w, &scr_h); sizex = r - l; sizey = b - t; posx = l; posy = scr_h - t - win->sizey; /* * Ghost sometimes send size or move events when the window hasn't changed. * One case of this is using compiz on linux. To alleviate the problem * we ignore all such event here. * * It might be good to eventually do that at Ghost level, but that is for * another time. */ if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || win->posy != posy) { win->sizex = sizex; win->sizey = sizey; win->posx = posx; win->posy = posy; /* debug prints */ if (G.debug & G_DEBUG_EVENTS) { const char *state_str; state = GHOST_GetWindowState(win->ghostwin); if (state == GHOST_kWindowStateNormal) { state_str = "normal"; } else if (state == GHOST_kWindowStateMinimized) { state_str = "minimized"; } else if (state == GHOST_kWindowStateMaximized) { state_str = "maximized"; } else if (state == GHOST_kWindowStateFullScreen) { state_str = "fullscreen"; } else { state_str = "<unknown>"; } printf("%s: window %d state = %s\n", __func__, win->winid, state_str); if (type != GHOST_kEventWindowSize) { printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); } } wm_window_make_drawable(wm, win); wm_draw_window_clear(win); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); #if defined(__APPLE__) || defined(WIN32) /* OSX and Win32 don't return to the mainloop while resize */ wm_event_do_handlers(C); wm_event_do_notifiers(C); wm_draw_update(C); #endif } } break; } case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; wmWindow *oldWindow; const char *path = GHOST_GetEventData(evt); if (path) { wmOperatorType *ot = WM_operatortype_find("WM_OT_open_mainfile", false); /* operator needs a valid window in context, ensures * it is correctly set */ oldWindow = CTX_wm_window(C); CTX_wm_window_set(C, win); WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "filepath", path); WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); CTX_wm_window_set(C, oldWindow); } break; } case GHOST_kEventDraggingDropDone: { wmEvent event; GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); int wx, wy; /* entering window, update mouse pos */ wm_get_cursor_position(win, &wx, &wy); win->eventstate->x = wx; win->eventstate->y = wy; wm_event_init_from_window(win, &event); /* copy last state, like mouse coords */ /* activate region */ event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; wm_event_add(win, &event); /* make blender drop event with custom data pointing to wm drags */ event.type = EVT_DROP; event.val = KM_RELEASE; event.custom = EVT_DATA_DRAGDROP; event.customdata = &wm->drags; event.customdatafree = 1; wm_event_add(win, &event); /* printf("Drop detected\n"); */ /* add drag data to wm for paths: */ if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { GHOST_TStringArray *stra = ddd->data; int a, icon; for (a = 0; a < stra->count; a++) { printf("drop file %s\n", stra->strings[a]); /* try to get icon type from extension */ icon = ED_file_extension_icon((char *)stra->strings[a]); WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP); /* void poin should point to string, it makes a copy */ break; /* only one drop element supported now */ } } break; } case GHOST_kEventNativeResolutionChange: // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); U.pixelsize = wm_window_pixelsize(win); BKE_userdef_state(); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); break; case GHOST_kEventTrackpad: { GHOST_TEventTrackpadData *pd = data; wm_convert_cursor_position(win, &pd->x, &pd->y); wm_event_add_ghostevent(wm, win, type, time, data); break; } case GHOST_kEventCursorMove: { GHOST_TEventCursorData *cd = data; wm_convert_cursor_position(win, &cd->x, &cd->y); wm_event_add_ghostevent(wm, win, type, time, data); break; } default: wm_event_add_ghostevent(wm, win, type, time, data); break; } } return 1; }
/** * Uses `screen->temp` tag to define what to do, currently it limits * to only one "temp" window for render out, preferences, filewindow, etc... * * \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS... * \return the window or NULL. */ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) { wmWindow *win_prev = CTX_wm_window(C); wmWindow *win; ScrArea *sa; Scene *scene = CTX_data_scene(C); const char *title; rcti rect = *rect_init; const short px_virtual = (short)wm_window_get_virtual_pixelsize(); /* changes rect to fit within desktop */ wm_window_check_position(&rect); /* test if we have a temp screen already */ for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) if (win->screen->temp) break; /* add new window? */ if (win == NULL) { win = wm_window_new(C); win->posx = rect.xmin; win->posy = rect.ymin; } /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */ win->sizex = BLI_rcti_size_x(&rect) * px_virtual; win->sizey = BLI_rcti_size_y(&rect) * px_virtual; if (win->ghostwin) { wm_window_set_size(win, win->sizex, win->sizey); wm_window_raise(win); } if (win->screen == NULL) { /* add new screen */ win->screen = ED_screen_add(win, scene, "temp"); } else { /* switch scene for rendering */ if (win->screen->scene != scene) ED_screen_set_scene(C, win->screen, scene); } win->screen->temp = 1; /* make window active, and validate/resize */ CTX_wm_window_set(C, win); WM_check(C); /* It's possible `win->ghostwin == NULL`. * instead of attempting to cleanup here (in a half finished state), * finish setting up the screen, then free it at the end of the function, * to avoid having to take into account a partially-created window. */ /* ensure it shows the right spacetype editor */ sa = win->screen->areabase.first; CTX_wm_area_set(C, sa); if (type == WM_WINDOW_RENDER) { ED_area_newspace(C, sa, SPACE_IMAGE); } else { ED_area_newspace(C, sa, SPACE_USERPREF); } ED_screen_set(C, win->screen); ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ if (sa->spacetype == SPACE_IMAGE) title = IFACE_("Blender Render"); else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) title = IFACE_("Blender User Preferences"); else if (sa->spacetype == SPACE_FILE) title = IFACE_("Blender File View"); else title = "Blender"; if (win->ghostwin) { GHOST_SetTitle(win->ghostwin, title); return win; } else { /* very unlikely! but opening a new window can fail */ wm_window_close(C, CTX_wm_manager(C), win); CTX_wm_window_set(C, win_prev); return NULL; } }